//
//  MsgGCDCtr.swift
//  sinaDemo
//
//  Created by admin on 2021/7/7.
//

import UIKit

class MsgGCDCtr: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        title = "GCD"
        /**** 死锁相关  **/
        //        test1()
        //        test2()
        //        test3()
        //        test4()
        //        test5()
        //        test6()
        //        test7()
        //        test8()
        //        test9()
        //        test10()
        /*   考线程  */
        //        test11()
                test12()
        
        
        /*   线程资源争抢问题 （锁） */
        let Btn = UIButton(title: "点我测试Lock", font: 15, backColor: .orange).then {
            $0.frame = CGRect(x: 100, y: 100, width: 200, height: 50)
            $0.addTarget(self, action: #selector(self.clickLock), for: .touchUpInside)
        }
        view.addSubview(Btn)
        
    }
    @objc private func clickLock(){
        //        OSSpinLockDemo.init().testMoney()
        //        OSUnfairLockDemo.init().testTickets()
//        PthreadMutexLockDemo.init().testAll()
        NSConditionLockDemo.init()
    }
    private func test1(){
        /*
         会造成死锁
         因为在主队列中执行任务2，但是在主队列中已经有一个任务（viewdidload）。
         主队列是串行队列，执行完一个任务再执行下一个，所以需要执行完viewdidload。
         但是执行完viewdidload需要执行任务2，造成死锁.
         执行结果1
         */
        print("执行1");
        let queue = DispatchQueue.main
        queue.sync {
            //同步执行，不具有开启新线程能力，需要立马执行
            print("执行2")
        }
        print("执行3")
    }
    private func test2(){
        /*
         不会造成死锁
         因为在主队列中执行任务2，但是任务2不需要马上执行，但是在主队列中已经有一个任务（viewdidload）。
         主队列是串行队列，执行完一个任务再执行下一个，所以需要执行完viewdidload。
         viewdidload中的任务2不需要马上执行，所以可以等等。所以结果就是132
         */
        print("执行1")
        let queue = DispatchQueue.main
        queue.async {
            //异步执行，不需要马上执行，具有新建线程的能力，但在主队列不会新建线程
            print(Thread.current)
            print("执行2")
        }
        print("执行3")
    }
    private func test3(){
        /*
         不会造成死锁
         因为此时的queue是自建的串行队列，并非是主队列。
         自建串行队列内并没有其他任务
         所以结果为123
         */
        print("1")
        let queue = DispatchQueue.init(label: "myqueue3",qos: .default)//默认是串行队列
        queue.sync {
            //任务立即执行,不会新建线程，在主线程执行任务
            print(Thread.current)
            print("2")
        }
        print("3")
    }
    private func test4(){
        /*
         不会造成死锁
         因为此时的queue是自建的串行队列，并非是主队列。
         自建串行队列内并没有其他任务
         所以结果为132
         */
        print("1")
        let queue = DispatchQueue.init(label: "myqueue4",qos: .default)//默认是串行队列
        queue.async {
            //任务不立即执行,会新建线程
            print(Thread.current)
            print("2")
        }
        print("3")
    }
    private func test5(){
        /*
         会造成死锁
         因为此时的queue是自建的串行队列，并非是主队列。
         自建串行队列内有2个任务分别是：任务block1和任务block2.
         任务block2是sync需要立即执行，但是串行队列内还有任务1没执行完，block1就类似test1中的viewdidload。
         不过死锁的是新建的子线程
         所以结果为142crash
         */
        print("1")
        let queue = DispatchQueue.init(label: "myqueue5",qos: .default)//默认是串行队列
        queue.async {
            //任务block1
            //任务不立即执行,会新建线程
            print(Thread.current)
            print("2")
            queue.sync {
                //死锁在这
                //任务block2
                print("3")
            }
        }
        print("4")
    }
    private func test6(){
        /*
         会造成死锁
         因为此时的queue是自建的串行队列，并非是主队列。
         自建串行队列内有2个任务分别是：任务block1和任务block2.
         任务block2是sync需要立即执行，但是串行队列内还有任务1没执行完，block1就类似test1中的viewdidload。
         不过死锁的是主线程
         所以结果为12crash
         */
        print("1")
        let queue = DispatchQueue.init(label: "myqueue6",qos: .default)//默认是串行队列
        queue.sync {
            //任务block1
            //任务立即执行,不会新建线程，此时还是主线程
            print(Thread.current)
            print("2")
            queue.sync {
                //任务block2
                print("3")
            }
        }
        print("4")
    }
    private func test7(){
        /*
         不会造成死锁
         因为此时的queue是自建的并发队列，队列内的任务可以异步执行。
         自建并发队列内有2个任务分别是：任务block1和任务block2.
         任务block2是sync需要立即执行
         所以结果为1234
         */
        print("1")
        let queue = DispatchQueue.init(label: "myqueue7",qos: .default,attributes: .concurrent)//并发队列
        queue.sync {
            //任务block1
            //任务立即执行,不会新建线程，此时还是主线程
            print(Thread.current)
            print("2")
            queue.sync {
                //任务block2
                print("3")
            }
        }
        print("4")
    }
    private func test8(){
        /*
         不会造成死锁
         因为此时的queue是自建的并发队列，队列内的任务可以异步执行。
         自建并发队列内有2个任务分别是：任务block1和任务block2.
         任务block2是sync需要立即执行
         所以结果为1423
         */
        print("1")
        let queue = DispatchQueue.init(label: "myqueue8",qos: .default,attributes: .concurrent)//并发队列
        queue.async {
            //任务block1
            //任务不立即执行,会新建线程
            print(Thread.current)
            print("2")
            queue.sync {
                //任务block2，立即执行，不会新建线程，此时还是在上次创建的子线程中
                print(Thread.current)
                print("3")
            }
        }
        print("4")
    }
    private func test9(){
        /*
         不会造成死锁
         因为此时的queue是自建的并发队列，队列内的任务可以异步执行。
         自建并发队列内有2个任务分别是：任务block1和任务block2.
         任务block2是async不需要立即执行
         所以结果为1423
         */
        print("1")
        let queue = DispatchQueue.init(label: "myqueue9",qos: .default,attributes: .concurrent)//并发队列
        queue.async {
            //任务block1
            //任务不立即执行,会新建线程
            print(Thread.current)
            print("2")
            queue.async {
                // MARK: - 有点疑问
                //任务block2，不立即执行，具备新建线程的能力，但不会新建线程 why？？？
                print(Thread.current)
                print("3")
            }
        }
        print("4")
    }
    private func test10(){
        /*
         不会造成死锁
         因为此时的queue是自建的并发队列，队列内的任务可以异步执行。
         自建并发队列内有2个任务分别是：任务block1和任务block2.
         任务block2是async不需要立即执行
         所以结果为1423
         */
        print("1")
        let queue = DispatchQueue.init(label: "myqueue10",qos: .default,attributes: .concurrent)//并发队列
        queue.async {
            //任务block1
            //任务不立即执行,会新建线程
            print(Thread.current)
            print("2")
        }
        queue.async {
            //任务block2，不立即执行，会新建线程
            print(Thread.current)
            print("3")
        }
        print("4")
    }
    
    
    //一些骚操作
    private func test11(){
        print("1")
        DispatchQueue.global().async {
            //为何是全局队列，async？  因为此时会新建线程，如果在主队列主线程的话，因为主线程一直运行，不用再次加runloop就会执行了
            print("2")
            //question1:
            self.perform(#selector(self.performDoSomething), with: nil, afterDelay: 0.0)//这句执行是在runloop中添加了一个定时器。但是runloop并没有跑起来。所以，只写这一句是不会执行的
            RunLoop.current.run(mode: .default, before: .distantFuture)//必须加上这一句
            //加上这一句后为何会最后执行，是因为runloop循环的原因，先处理source事件，再处理timer唤醒事件
            
            //这一句没事，是直接调用的runtime的sendmsg相当于直接self.performDoSomething
            //self.perform(#selector(self.performDoSomething))
            
        }
        print("3")
    }
    private func test12(){
        /*执行结果132*/
        print("1")
        let xmthread:Thread = Thread.init {
            print(Thread.current)
            print("2")
        }
        //下面语句不会有效果，因为此时xmtread线程已经销毁了。如果利用runloop实现线程保活就可以。
        self.perform(#selector(self.performDoSomething), on: xmthread, with: nil, waitUntilDone: false)
        xmthread.start()
        print("3")
    }
    @objc private func performDoSomething(){
        print("performDoSomething")
    }
}
